package com.huilian.iotbox.client.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.github.pagehelper.PageHelper;
import com.huilian.iotbox.aliyun.service.PubService;
import com.huilian.iotbox.client.dao.MemberDao;
import com.huilian.iotbox.client.security.enums.JwtRedisEnum;
import com.huilian.iotbox.client.security.jwt.util.JwtTokenUtil;
import com.huilian.iotbox.client.security.properties.SecurityProperties;
import com.huilian.iotbox.client.service.*;
import com.huilian.iotbox.data.cmd.HuiLianDuiBiJiPositiveDataFrameCMD;
import com.huilian.iotbox.data.cmd.PositiveDataFrameCMD;
import com.huilian.iotbox.data.common.RedisHelper;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.config.AlipayConfig;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.properties.ImageProperties;
import com.huilian.iotbox.data.service.AppletOrOfficialAccountCommonService;
import com.huilian.iotbox.data.service.MemberCommonService;
import com.huilian.iotbox.data.service.MemberStoreBalanceCommonService;
import com.huilian.iotbox.data.utils.DateTimeUtils;
import com.huilian.iotbox.data.utils.MD5SignUtil;
import com.huilian.iotbox.data.utils.SnowflakeIdWorker;
import com.huilian.iotbox.data.utils.Util;
import com.huilian.iotbox.data.vo.*;
import com.huilian.tool.ali.applet.service.AliAppletService;
import com.huilian.tool.applet.wechat.service.WeChatAppletService;
import com.huilian.tool.common.config.AppletAliConfig;
import com.huilian.tool.douyin.applet.service.DouYinAppletService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class MemberServiceImpl implements MemberService {

    @Value("${huilian.iot.productKey}")
    private String productKey;
    @Autowired
    private MemberDao memberDao;
    @Autowired
    private PubService pubService;
    @Autowired
    private RedisHelper redisHelper;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private AgencyService agencyService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private AppletAliConfig appletAliConfig;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Resource
    private ImageProperties imageProperties;
    @Resource
    private AliAppletService aliAppletService;
    @Resource
    private OrderItemService orderItemService;
    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private MemberCommonService memberCommonService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private DouYinAppletService douYinAppletService;
    @Autowired
    private MerchantStoreService merchantStoreService;
    @Autowired
    private MemberStoreBalanceService memberStoreBalanceService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private CommodityStoreUpDownService commodityStoreUpDownService;
    @Autowired
    private MemberStoreBalanceCommonService memberStoreBalanceCommonService;
    @Autowired
    private AppletOrOfficialAccountCommonService appletOrOfficialAccountCommonService;
    @Resource
    private WeChatAppletService weChatAppletService;


    @Override
    public Member getMemberByKeyWordByALiUnionId(String keyWord) {
        return memberDao.getMemberByKeyWordByALiUnionId(keyWord);
    }

    @Override
    public Integer addMember(Member memberInfo) {
        return memberDao.insert(memberInfo);
    }

    @Override
    public MemberDto queryById(Long memberId) {
        return memberDao.queryById(memberId);
    }

    @Override
    public ServerResponse queryInfoById(MemberDto memberDto) {
        MemberVo memberVo = memberDao.queryInfoById(memberDto);
        if (!StringUtils.isEmpty(memberVo.getFetchCoinPwd())) {
            memberVo.setFetchCoinPwd(null);
            memberVo.setHaveFetchCoinPwd(true);
        } else {
            memberVo.setHaveFetchCoinPwd(false);
        }

        return ServerResponse.createBySuccess(memberVo);
    }


    @Override
    public int updateById(Member m) {
        return memberDao.updateById(m);
    }


    @Override
    public ServerResponse findMemberOrderList(CommonOrderDto commonOrderDto) {
        if (StringUtils.isEmpty(commonOrderDto.getType())) {
            return ServerResponse.createByErrorMessage("type不能为空");
        }

        log.info("commonOrderDto：");
        log.info(JSON.toJSONString(commonOrderDto));

        PageHelper.startPage(commonOrderDto.getPageNum(), commonOrderDto.getPageSize());
        List<CommonOrderDto> list = memberDao.findMemberOrderList(commonOrderDto);

        for (CommonOrderDto forCommonOrder : list) {
            if (DeviceTypeEnum.VENDING_MACHINE.getCode().equals(forCommonOrder.getDeviceTypeId()) ||
                    DeviceTypeEnum.SCREEN_VENDING_MACHINE.getCode().equals(forCommonOrder.getDeviceTypeId()) ||
                    DeviceTypeEnum.BLEND_VENDING_MACHINE.getCode().equals(forCommonOrder.getDeviceTypeId()) ||
                    DeviceTypeEnum.OPEN_DOOR_VENDING_MACHINE.getCode().equals(forCommonOrder.getDeviceTypeId()) ) {
                //售货机商品
                List<CommodityVo> commodityList = new ArrayList<>();
                List<OrderItemVo> orderItemVoList = orderItemService.getCommodityAndOrderItemByOrderId(forCommonOrder.getOrderId());
                for (OrderItemVo orderItemVo : orderItemVoList) {
                    CommodityVo commodityVo = new CommodityVo();
                    commodityVo.setNum(orderItemVo.getNum());
                    commodityVo.setPrice(orderItemVo.getPrice());
                    commodityVo.setOrderItemShipmentStatus(orderItemVo.getShipmentStatus());
                    commodityVo.setOrderItemShipmentFailureNum(orderItemVo.getShipmentFailureNum());
                    commodityVo.setName(orderItemVo.getCommodityName());
                    commodityList.add(commodityVo);
                }
                forCommonOrder.setCommodityList(commodityList);
            } else {
                if (!ObjectUtils.isEmpty(forCommonOrder.getCommodityStoreUpDownIdList())) {
                    List<CommodityVo> commodityList = new ArrayList<>();
//                [{"commodityStoreUpDownId":77,"num":1,"price":20.00},{"commodityStoreUpDownId":75,"num":1,"price":5.00}]

                    List<CommodityStoreUpDownDto> commodityStoreUpDownList = JSONObject.parseArray(forCommonOrder.getCommodityStoreUpDownIdList(), CommodityStoreUpDownDto.class);
                    for (CommodityStoreUpDownDto forCommodityStoreUpDown : commodityStoreUpDownList) {
                        CommodityVo commodityVo = commodityStoreUpDownService.findOneCommodityByStoreUpDownId(forCommodityStoreUpDown.getCommodityStoreUpDownId());
                        if (ObjectUtils.isEmpty(commodityVo)) {
                            commodityVo = new CommodityVo();
                            commodityVo.setName("未知商品");
                        }
                        commodityVo.setNum(forCommodityStoreUpDown.getNum());
                        commodityVo.setPrice(forCommodityStoreUpDown.getPrice());
                        commodityList.add(commodityVo);
                    }

                    forCommonOrder.setCommodityList(commodityList);
                }
            }

        }
        return ServerResponse.createBySuccess(list);
    }

    /**
     * 查询单个订单详情
     */
    @Override
    public ServerResponse findMemberOrderOne(CommonOrderDto commonOrderDto) {
        if (StringUtils.isEmpty(commonOrderDto.getType())) {
            return ServerResponse.createByErrorMessage("type不能为空");
        }

        log.info("commonOrderDto：");
        log.info(JSON.toJSONString(commonOrderDto));

        CommonOrderDto data = memberDao.findMemberOrderOne(commonOrderDto);
        if (!ObjectUtils.isEmpty(data)) {
            if (DeviceTypeEnum.VENDING_MACHINE.getCode().equals(data.getDeviceTypeId()) ||
                    DeviceTypeEnum.SCREEN_VENDING_MACHINE.getCode().equals(data.getDeviceTypeId()) ||
                    DeviceTypeEnum.BLEND_VENDING_MACHINE.getCode().equals(data.getDeviceTypeId()) ||
                    DeviceTypeEnum.OPEN_DOOR_VENDING_MACHINE.getCode().equals(data.getDeviceTypeId()) ) {
                //售货机商品
                List<CommodityVo> commodityList = new ArrayList<>();
                List<OrderItemVo> orderItemVoList = orderItemService.getCommodityAndOrderItemByOrderId(data.getOrderId());
                for (OrderItemVo orderItemVo : orderItemVoList) {
                    CommodityVo commodityVo = new CommodityVo();
                    commodityVo.setNum(orderItemVo.getNum());
                    commodityVo.setPrice(orderItemVo.getPrice());
                    commodityVo.setOrderItemShipmentStatus(orderItemVo.getShipmentStatus());
                    commodityVo.setOrderItemShipmentFailureNum(orderItemVo.getShipmentFailureNum());
                    commodityVo.setName(orderItemVo.getCommodityName());
                    commodityVo.setFileName(orderItemVo.getFileName());
                    commodityList.add(commodityVo);
                }
                data.setCommodityList(commodityList);
            } else {
                if (!ObjectUtils.isEmpty(data.getCommodityStoreUpDownIdList())) {
                    List<CommodityStoreUpDownDto> commodityStoreUpDownList = JSONObject.parseArray(data.getCommodityStoreUpDownIdList(), CommodityStoreUpDownDto.class);
                    List<CommodityVo> commodityList = new ArrayList<>();
//                [{"commodityStoreUpDownId":77,"num":1,"price":20.00},{"commodityStoreUpDownId":75,"num":1,"price":5.00}]
                    for (CommodityStoreUpDownDto forCommodityStoreUpDown : commodityStoreUpDownList) {
                        CommodityVo commodityVo = commodityStoreUpDownService.findOneCommodityByStoreUpDownId(forCommodityStoreUpDown.getCommodityStoreUpDownId());
                        if (ObjectUtils.isEmpty(commodityVo)) {
                            commodityVo = new CommodityVo();
                            commodityVo.setName("未知商品");
                        }
                        commodityVo.setNum(forCommodityStoreUpDown.getNum());
                        commodityVo.setPrice(forCommodityStoreUpDown.getPrice());
                        commodityList.add(commodityVo);
                    }
                    data.setCommodityList(commodityList);
                }
            }

        }
        return ServerResponse.createBySuccess(data);
    }

    /**
     * 支付宝小程序登录
     *
     * @param aliUserDto
     * @return
     */
    @Override
    public ServerResponse aliLogin(AliUserDto aliUserDto) {
        if (StringUtils.isEmpty(aliUserDto.getAppId())) {
            return ServerResponse.createByErrorMessage("APPID不能为空，请及时更新小程序");
        }

        final AppletOrOfficialAccount appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneByALiAppId(aliUserDto.getAppId());
        if (StringUtils.isEmpty(appletOrOfficialAccount)) {
            return ServerResponse.createByErrorMessage("未找到支付宝小程序信息，APPID：" + aliUserDto.getAppId());
        }

        final AliUserDto param = alipayAuth(aliUserDto.getAuthCode(), appletOrOfficialAccount.getALiAppId(), appletOrOfficialAccount.getALiPrivateKey(), appletOrOfficialAccount.getALiPublicKey());
        aliUserDto.setAliUserId(param.getAliUserId());
        aliUserDto.setUserId(param.getUserId());
        if (StringUtils.isEmpty(param.getUserId())) {
            return ServerResponse.createByErrorMessage("获取用户信息失败");
        }

        final String keyWord = param.getAliUserId();
        if (StringUtils.isEmpty(keyWord)) {
            return ServerResponse.createByErrorMessage("获取用户信息失败");
        }

        Member memberInfo = memberService.getMemberByKeyWordByALiUnionId(keyWord);

        if (StringUtils.isEmpty(memberInfo)) {
            memberInfo = new Member();
            memberInfo.setNickName("支付宝用户");
            memberInfo.setZfbUserId(aliUserDto.getUserId());
            memberInfo.setZfbUnionId(keyWord);
            memberInfo.setHeadImgUrl(imageProperties.getStaticFileUrl() + "/image/common/member-header-image-default.svg");
            memberInfo.setStatus(MemberStatusEnum.NORMAL.getCode());
            log.info(JSON.toJSONString(memberInfo));
            memberService.addMember(memberInfo);
        }

        final String token = this.generateToken(memberInfo);
        MemberVo memberVo = new MemberVo();
        memberVo.setToken(token);
        memberVo.setId(memberInfo.getId());
        memberVo.setNickName(memberInfo.getNickName());
        memberVo.setHeadImgUrl(memberInfo.getHeadImgUrl());
        memberVo.setMobile(memberInfo.getMobile());
        if (StringUtils.isEmpty(memberInfo.getFetchCoinPwd())) {
            memberVo.setHaveFetchCoinPwd(false);
        } else {
            memberVo.setHaveFetchCoinPwd(true);
        }

        appletOrOfficialAccountCommonService.dedicatedExistConsume(appletOrOfficialAccount, memberInfo);
        return ServerResponse.createBySuccess(memberVo);
    }

    /**
     * 获取手机号
     *
     * @param memberDto
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse getPhoneNumber(MemberDto memberDto) throws Exception {

        /**获取手机号-begin*/
        if (StringUtils.isEmpty(memberDto.getChannelType())) {
            return ServerResponse.createByErrorMessage("channelType不能为空");
        }

        MemberDto memberDto1 = memberService.queryById(memberDto.getId());
        if (!StringUtils.isEmpty(memberDto1.getMobile())) {
            return ServerResponse.createByErrorMessage("已设置手机号码，如需更改请前往个人中心修改");
        }

        AppletOrOfficialAccount appletOrOfficialAccount = null;
        if (StringUtils.isEmpty(memberDto.getAppId())) {
            if (ChannelTypeEnum.WX.getStr().equalsIgnoreCase(memberDto.getChannelType())) {
                log.info("AppId为空，wx");
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(1);
            } else if (ChannelTypeEnum.Ali.getStr().equalsIgnoreCase(memberDto.getChannelType())) {
                log.info("AppId为空，ali");
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(2);
            } else {
                throw new RuntimeException("平台类型有误");
            }
        } else {
            if (ChannelTypeEnum.WX.getStr().equalsIgnoreCase(memberDto.getChannelType())) {
                log.info("AppId不为空，wx");
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneByWeChatAppId(memberDto.getAppId());
            } else if (ChannelTypeEnum.Ali.getStr().equalsIgnoreCase(memberDto.getChannelType())) {
                log.info("AppId不为空，ali");
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneByALiAppId(memberDto.getAppId());
            } else {
                throw new RuntimeException("平台类型有误");
            }
        }

        if (StringUtils.isEmpty(appletOrOfficialAccount)) {
            return ServerResponse.createByErrorMessage("请联系平台，小程序信息未录入");
        }

        Map<String, String> map = new HashMap<>();
        if (ChannelTypeEnum.WX.getStr().equalsIgnoreCase(memberDto.getChannelType())) {
            if (StringUtils.isEmpty(memberDto.getCode())) {
                return ServerResponse.createByErrorMessage("code不能为空");
            }
            final String redisKey = String.format(RedisKey.WEI_XIN_CLIENT_APPLET_ACCESS_TOKEN, appletOrOfficialAccount.getWeChatAppId());
            final String phoneNumber = weChatAppletService.getUserPhoneNumber(memberDto.getCode(), appletOrOfficialAccount.getWeChatAppId(), appletOrOfficialAccount.getWeChatAppSecret(), redisKey);
            map.put("mobile", phoneNumber);
        } else if (ChannelTypeEnum.Ali.getStr().equalsIgnoreCase(memberDto.getChannelType())) {
            if (StringUtils.isEmpty(memberDto.getSign())) {
                return ServerResponse.createByErrorMessage("sign不能为空");
            }
            if (StringUtils.isEmpty(memberDto.getResponse())) {
                return ServerResponse.createByErrorMessage("response不能为空");
            }
            map = aliAppletService.getPhoneNumber(memberDto.getSign(), memberDto.getResponse(), appletOrOfficialAccount.getALiPublicKey(), appletOrOfficialAccount.getALiAesKey());
        } else {
            return ServerResponse.createByErrorMessage("channelType不能为空");
        }

        String mobile = map.get("mobile");
        if (StringUtils.isEmpty(mobile)) {
            throw new RuntimeException("会员未绑定手机号或获取失败");
        }
        /**获取手机号-end*/

        List<Member> memberList = memberDao.findAllMemberByMobile(mobile);
        if (memberList.size() == 0 || (memberList.size() == 1 && memberList.get(0).getId().compareTo(memberDto.getId()) == 0)) {
            return this.updateMemberInfo(memberDto, mobile);
        }

        Long memberId = memberCommonService.mergeMemberInfo(memberList, memberDto, mobile);

        // 删除相同手机号的账号登录token
        final String k = JwtRedisEnum.getTokenKey(String.valueOf(memberId), "");
        log.info("key:" + k);

        Set<String> keys = redisHelper.keys(k + "*");
        log.info("keys：" + keys.toString());
        for (String key : keys) {
            Boolean delete = stringRedisTemplate.delete(key);
            log.info("key：{}，删除结果：", key, delete);
        }

        return this.updateMemberInfo(memberDto, mobile);
    }

    private ServerResponse updateMemberInfo(MemberDto memberDto, String mobile) {
        Member newMember = new Member();
        newMember.setId(memberDto.getId());
        newMember.setMobile(mobile);
        newMember.setNickName(memberDto.getNickName());
        newMember.setHeadImgUrl(memberDto.getHeadImgUrl());
        memberService.updateById(newMember);
        return ServerResponse.createBySuccess(newMember);
    }

    /**
     * 返回加密后的会员核销码
     *
     * @param memberDto
     * @return
     */
    @Override
    public ServerResponse getEncryptCheckCode(MemberDto memberDto, HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Long memberId = memberDto.getId();
        //根据ip 会员id，判断缓存是否存在,存在则返回过期时间
        String key = String.format(RedisKey.MEMBERSHIP_CODE_REFRESH, request.getRemoteAddr(), memberId);
        if (Boolean.TRUE.equals(redisCacheTemplate.hasKey(key))) {
            long expiryDate = redisCacheTemplate.getExpire(key, TimeUnit.SECONDS);
            return ServerResponse.createBySuccess(expiryDate);
        }
        // 新建缓存
        final String userNextId = SnowflakeIdWorker.nextId();
        String detailKey = String.format(RedisKey.MEMBER_QR, userNextId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("memberId", memberId);
        map.put("tempId", userNextId);
        map.put("memberId", String.valueOf(memberId));

        LocalDateTime now = LocalDateTime.now();
        ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai"); // 东八区时区
        ZoneId madridZone = ZoneId.of("Europe/Madrid"); // 马德里时区
        ZonedDateTime expiration = now.atZone(shanghaiZone);
        if (StringUtils.isEmpty(memberDto.getLanguage()) || memberDto.getLanguage().equals("zh")) {
            redisCacheTemplate.opsForValue().set(detailKey, jsonObject, 24, TimeUnit.HOURS);
        } else if (memberDto.getLanguage().equals("es")) {
            expiration = expiration.withZoneSameInstant(madridZone);
            redisCacheTemplate.opsForValue().set(detailKey, jsonObject, 24 - 6, TimeUnit.HOURS);
        }
        redisCacheTemplate.opsForValue().set(key, jsonObject, 10, TimeUnit.SECONDS);
        map.put("validity", expiration.plusDays(1).format(DateTimeFormatter.ofPattern("MM-dd HH:mm:ss")));
        return ServerResponse.createBySuccess(map);
    }


    /**
     * 修改用户信息
     *
     * @param memberDto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse updateInfo(MemberDto memberDto) {

        if (StringUtils.isEmpty(memberDto.getId())) {
            return ServerResponse.createByErrorMessage("会员ID不能为空");
        }

        if (StringUtils.isEmpty(memberDto.getHeadImgUrl())) {
            return ServerResponse.createByErrorMessage("会员头像不能为空");
        }

        if (StringUtils.isEmpty(memberDto.getNickName())) {
            return ServerResponse.createByErrorMessage("会员昵称不能为空");
        }

        if (StringUtils.isEmpty(memberDto.getMobile())) {
            return ServerResponse.createByErrorMessage("会员手机号不能为空");
        }

        List<Member> memberList = memberDao.findAllMemberByMobile(memberDto.getMobile());
        if (memberList.size() == 0 || (memberList.size() == 1 && memberList.get(0).getId().compareTo(memberDto.getId()) == 0)) {
            return this.updateMemberInfo(memberDto, memberDto.getMobile());
        }

        Long memberId = memberCommonService.mergeMemberInfo(memberList, memberDto, memberDto.getMobile());

        // 删除相同手机号的账号登录token
        final String k = JwtRedisEnum.getTokenKey(String.valueOf(memberId), "");
        log.info("key:" + k);

        Set<String> keys = redisHelper.keys(k + "*");
        log.info("keys：" + keys.toString());
        for (String key : keys) {
            Boolean delete = stringRedisTemplate.delete(key);
            log.info("key：{}，删除结果：", key, delete);
        }

        return this.updateMemberInfo(memberDto, memberDto.getMobile());
    }

    @Override
    public void delete(Long id) {
        memberDao.delete(id);
    }

    @Override
    public Member getMemberByWeChatUnionId(String keyWord) {
        return memberDao.getMemberByWeChatUnionId(keyWord);
    }

    /**
     * 安卓屏会员扫码登录，发送mqtt通知apk,memberId
     *
     * @param member
     * @return
     */
    @Override
    public ServerResponse noticeAppLoginSuc(MemberDto member) {
        MemberStoreBalanceDto memberStoreBalance = new MemberStoreBalanceDto();
        memberStoreBalance.setDeviceNo(member.getDeviceNo());
        memberStoreBalance.setMemberId(member.getId());
        MemberStoreBalanceVo memberStoreBalanceVo = memberStoreBalanceService.findMemberStoreBalanceByDeviceNoAndMemberId(memberStoreBalance);
        if (StringUtils.isEmpty(memberStoreBalanceVo)) {
            DeviceVo deviceVo = deviceService.findOneDeviceByDeviceNo(member.getDeviceNo());
            memberStoreBalanceCommonService.add(member.getId(), deviceVo.getMerchantStoreId(), deviceVo.getUserId(), deviceVo.getDeviceNo());
            memberStoreBalanceVo = memberStoreBalanceService.findMemberStoreBalanceByDeviceNoAndMemberId(memberStoreBalance);
        }
        if (StringUtils.isEmpty(memberStoreBalanceVo)) {
            return ServerResponse.createByErrorMessage("会员添加失败");
        }

        final String command = PositiveDataFrameCMD.penetrate(HuiLianDuiBiJiPositiveDataFrameCMD.noticeAppLoginMember(memberStoreBalanceVo.getId()));

        pubService.pub(command, member.getDeviceNo(), productKey);
        return ServerResponse.createBySuccess();
    }


    @Override
    public Member getMemberByWeChatOpenId(String openId) {
        return memberDao.getMemberByWeChatOpenId(openId);
    }

    @Override
    public Member findBasicInformationById(Long memberId) {
        MemberDto memberDto = memberDao.queryById(memberId);
        return Member.builder().nickName(memberDto.getNickName()).headImgUrl(memberDto.getHeadImgUrl()).mobile(memberDto.getMobile()).build();
    }


    /**
     * 这里模拟账户密码登录 颁发token
     *
     * @param memberInfo
     * @return
     */
    private String generateToken(Member memberInfo) {
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(memberInfo, null, null);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        final String randomKey = jwtTokenUtil.getRandomKey();
        final String token = jwtTokenUtil.generateToken(memberInfo.getId().toString(), randomKey);

        // 存到redis；项目名称:jwt:会员ID
        stringRedisTemplate.opsForValue().set(JwtRedisEnum.getTokenKey(memberInfo.getId().toString(), randomKey), token, securityProperties.getJwt().getExpiration(), TimeUnit.SECONDS);

        // 将认证信息存到redis，方便后期业务用，也方便JwtAuthenticationTokenFilter用；authentication:会员ID
//        stringRedisTemplate.opsForValue().set(JwtRedisEnum.getAuthenticationKey(memberInfo.getId().toString(), randomKey), JSON.toJSONString(authentication), securityProperties.getJwt().getExpiration(), TimeUnit.SECONDS);

        return token;
    }

    public AliUserDto alipayAuth(String authCode, String appId, String privateKey, String publicKey) {
        try {
            AliUserDto aliUserDto = new AliUserDto();
            StringBuffer url = new StringBuffer();
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ALIPAY_GATEWAY_URL, appletAliConfig.getAppId(), appletAliConfig.getPrivateKey(), "json", "UTF-8", appletAliConfig.getPublicKey(), "RSA2");

            AlipaySystemOauthTokenRequest res = new AlipaySystemOauthTokenRequest();
            res.setCode(authCode);
            res.setGrantType("authorization_code");
            try {
                AlipaySystemOauthTokenResponse execute = alipayClient.execute(res);
                String userId = execute.getUserId();
                aliUserDto.setUserId(userId);
                aliUserDto.setAliUserId(execute.getAlipayUserId());
                return aliUserDto;
            } catch (AlipayApiException e) {
                //处理异常
                log.error(e.getErrMsg());
                throw new RuntimeException("获取支付宝userId异常");
            }

        } catch (Exception e) {
            log.error(e.toString());
            throw new RuntimeException("获取支付宝userId异常");
        }
    }

    @Override
    public ServerResponse findUnionIdThereById(MemberDto memberDto) {
        Member member = memberDao.findUnionIdThereById(memberDto.getId());
        if (StringUtils.isEmpty(member)) {
            throw new RuntimeException("会员ID有误");
        }

        Boolean h5FillInMemberInfo = true;
        if (StringUtils.isEmpty(memberDto.getDeviceNo())) {
            throw new RuntimeException("设备号不能为空");
        }
        DeviceVo deviceVo = deviceService.findOneDeviceByDeviceNo(memberDto.getDeviceNo());

        JSONObject jsonObject = new JSONObject();
        if (!StringUtils.isEmpty(deviceVo)) {
            h5FillInMemberInfo = deviceVo.getH5FillInMemberInfo();

            Agency agency = agencyService.getAgencyById(deviceVo.getAgencyId());
            if (!StringUtils.isEmpty(agency) && agency.getCustomLogo() && !StringUtils.isEmpty(agency.getMobileLogoFileName())) {
                jsonObject.put("mobileLogoFileName", agency.getMobileLogoFileName());
                jsonObject.put("name", agency.getName());
            }
        }

        /**
         * 支付宝不需要
         * 有officialAccountOpenId，没unionId需要
         */
        if (h5FillInMemberInfo) {
            if (!StringUtils.isEmpty(member.getOfficialAccountOpenId())) {
                jsonObject.put("officialAccountOpenId", member.getOfficialAccountOpenId());
            }

            if (!member.getUserAgreement() || !member.getPersonalProtectionPolicy() || !member.getAcquiredInfo()) {
                jsonObject.put("isGet", true);
            } else {
                jsonObject.put("isGet", false);
            }
        } else {
            jsonObject.put("isGet", false);
        }
        return ServerResponse.createBySuccess(jsonObject);
    }

    @Override
    public ServerResponse acquiredInfo(MemberDto memberFromReq) {
        Member m = new Member();
        m.setId(memberFromReq.getId());
        m.setUserAgreement(true);
        m.setPersonalProtectionPolicy(true);
        m.setAcquiredInfo(true);
        memberDao.updateById(m);
        return ServerResponse.createBySuccess();
    }

    @Override
    public Member getMemberByWeChatOfficialAccountOpenId(String officialAccountOpenId) {
        return memberDao.getMemberByWeChatOfficialAccountOpenId(officialAccountOpenId);
    }

    @Override
    public List<Member> findAllMemberByCondition(Member memberCondition) {
        return memberDao.findAllMemberByCondition(memberCondition);
    }
}
